package ThreadRunableVolite;

/**
 * @author Ajie
 * @date 8/11/21
 * @function 题目：3个线程循环打印ABC，其中A打印3次，B打印2次，C打印1次，
 * <p>  sync notify wait .
 *  单独封装打印类。+3个thread
 * 解答参考 https://blog.csdn.net/weixin_39723337/article/details/80352783
 */
public class ThreadOrderAB_1SyncWaitNotify {
    public static void main(String[] args) throws InterruptedException {
        ABCPrint abcPrint = new ThreadOrderAB_1SyncWaitNotify.ABCPrint();
        new Thread(new ThreadOrderAB_1SyncWaitNotify.RunnableA(abcPrint), "Thread-A").start();
        Thread threadb = new Thread(new RunnableB(abcPrint), "Thread-B");
        Thread threadc = new Thread(new RunnableC(abcPrint), "Thread-C");
        Thread.sleep(100);
        threadb.start();
        Thread.sleep(100);
        threadc.start();

    }

   static class RunnableA implements Runnable {
        private ThreadOrderAB_1SyncWaitNotify.ABCPrint abcPrint;

        public RunnableA(ThreadOrderAB_1SyncWaitNotify.ABCPrint abcPrint) {
            this.abcPrint = abcPrint;
        }

        @Override
        public void run() {
            abcPrint.printA();
        }
    }

    static class RunnableB implements Runnable {
        private ThreadOrderAB_1SyncWaitNotify.ABCPrint abcPrint;

        public RunnableB(ThreadOrderAB_1SyncWaitNotify.ABCPrint abcPrint) {
            this.abcPrint = abcPrint;
        }

        @Override
        public void run() {
            abcPrint.printB();
        }
    }

    static class RunnableC implements Runnable {
        private ThreadOrderAB_1SyncWaitNotify.ABCPrint abcPrint;

        public RunnableC(ThreadOrderAB_1SyncWaitNotify.ABCPrint abcPrint) {
            this.abcPrint = abcPrint;
        }

        @Override
        public void run() {
            abcPrint.printC();
        }
    }

    static class ABCPrint {
        private volatile int num = 0;
        private int maxCount = 100;
        private volatile int state = 1;
        private volatile boolean isOUT = false; //TODO 为了最后退出所有线程。

        public void printA() {

            while (true)//一直循环
                synchronized (this) {
                    if (num > maxCount) {
                        isOUT  = true;
                        this.notifyAll();
                        return;//退出
                    }
                    while (state != 1 && !isOUT ) {//A wait
                        try {
                            this.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    for (int i = 0; i < 3 && !isOUT; i++) {//表示 打印3次
                        System.out.println("thread:" + Thread.currentThread() + " -- " + (num++));
                    }
                    //打印A线程执行完 ，通知打印B线程
                    state = 2;
                    System.out.println("A-->B :"+state);
                    this.notifyAll();
                }
        }

        public void printB() {
            while (true)//一直循环
                synchronized (this) {
                    if (num > maxCount) {
                        isOUT  = true;
                        this.notifyAll();
                        return;//退出
                    }
                    while (state != 2 && !isOUT) {//B wait
                        try {
                            this.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    for (int i = 0; i < 2 && !isOUT; i++) {//表示 打印2次
                        System.out.println("thread:" + Thread.currentThread() + " -- " + (num++));
                    }
                    //打印B线程执行完 ，通知打印c线程
                    state = 3;
                    System.out.println("B-->C :"+state);
                    this.notifyAll();
                }
        }

        public void printC() {
            while (true)//一直循环
                synchronized (this) {
                    if (num > maxCount) {
                        isOUT  = true;
                        this.notifyAll();
                        return;//退出
                    }
                    while (state != 3 && !isOUT) {
                        try {
                            this.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
//                if (num > maxCount) return;
                    for (int i = 0; i < 1 && !isOUT; i++) {//表示 打印1次
                        System.out.println("thread:" + Thread.currentThread() + " -- " + (num++));
                    }
                    //打印C线程执行完 ，通知打印A线程
                    state = 1;
                    System.out.println("C-->A :"+state);
                    this.notifyAll();
                }
        }
    }
}

